#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>

#include<netinet/in.h>
#include<arpa/inet.h>

extern int ret;

int get_pic()
{
    int fd = open("/dev/video0",O_RDWR);
    if(fd==-1)
    {
        perror("打开摄像头失败\n");
        return -1;
    }

    struct v4l2_capability cap;
    ioctl(fd,VIDIOC_QUERYCAP,&cap);

    struct v4l2_format vfmt;
    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vfmt.fmt.pix.width = 640;
    vfmt.fmt.pix.height = 480;
    vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
    vfmt.fmt.pix.field = V4L2_FIELD_NONE;

    int ret = ioctl(fd,VIDIOC_S_FMT,&vfmt);
    if(ret==-1)
    {
        perror("设置摄像头格式失败\n");
        return -1;
    }

    struct v4l2_requestbuffers reqbuf;
    reqbuf.count = 4;
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;

    ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuf);
    if(ret==-1)
    {
        perror("申请摄像头缓冲区失败\n");
        return -1;
    }

    unsigned char *mptr[4];
    unsigned int size[4];
    struct v4l2_buffer mapbuffer;
    mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    for (int i=0;i<4;i++)
    {
        mapbuffer.index = i;
        ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer);
        if(ret==-1)
        {
            perror("查询摄像头缓冲区失败\n");
            return -1;
        }
        mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);
        size[i] = mapbuffer.length;
        ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);
        if(ret==-1)
        {
            perror("映射摄像头缓冲区失败\n");
            return -1;
        }
    }
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    // int type = V4L2_BUF_TYPE_META_CAPTURE;
    ret = ioctl(fd,VIDIOC_STREAMON,&type);
    if(ret==-1)
    {
        perror("开启摄像头数据流失败\n");
        return -1;
    }

    struct v4l2_buffer readbuf;
    readbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(fd,VIDIOC_DQBUF,&readbuf);
    if(ret==-1)
    {
        perror("读取摄像头数据失败\n");
        return -1;
    }

    FILE* file=fopen("./carPlate.jpg","w+");
    fwrite(mptr[readbuf.index],1,size[readbuf.index],file);
    fclose(file);

    ret = ioctl(fd,VIDIOC_QBUF,&readbuf);
    if (ret==-1)
    {
        perror("重新入队摄像头数据失败\n");
        return -1;
    }

    ret = ioctl(fd,VIDIOC_STREAMOFF,&type);
    for (int i=0;i<4;i++)
    {
        munmap(mptr[i],size[i]);
    }

    close(fd);
    return 0;
} 



/*****************************************************************************/ 
//服务器初始化 返回套件字
/*****************************************************************************/ 
int server_init(char *ip,int port)
{
	//1.创建套接字 --> socket
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		perror("socket");
		return -1;
	}
	//2.绑定ip和端口 --> bind
	struct sockaddr_in s_addr = {
		.sin_family  = AF_INET,
		.sin_port    = htons(port),
		.sin_addr    = {
			.s_addr  = inet_addr(ip), 
		},
		.sin_zero    = {0},
	};

	socklen_t s_len = sizeof(s_addr);

	if(bind(sockfd, (struct sockaddr *)&s_addr, s_len) < 0)
	{
		perror("bind");
		close(sockfd);
		return -1;
	}
	//3.设置监听数 --> listen
	ret = listen(sockfd,20);
	if(ret<0)
	{
		perror("listen");
		return -1;
	}
	return sockfd;
}
